/*
 * Copyright 2009 by Tran Nhut Trung.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.gdevelop.gwtxp.rebind.gwt;


import com.gdevelop.gwtxp.rebind.AbstractTag;
import com.gdevelop.gwtxp.rebind.Tag;
import com.gdevelop.gwtxp.rebind.el.ELParser;
import com.gdevelop.gwtxp.rebind.el.Node;

import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JParameterizedType;
import com.google.gwt.core.ext.typeinfo.JType;
import com.google.gwt.core.ext.typeinfo.NotFoundException;
import com.google.gwt.user.client.ui.ListBox;

import org.w3c.dom.Attr;


public class ListBoxTag extends AbstractTag{
  public ListBoxTag() {
  }

  public Class getUIClass() {
    return ListBox.class;
  }

  public void generateAddUI(Tag child) {
    // No-op
  }
  
  protected void generateSetAttributeByExpression(Attr attr) throws NotFoundException {
    if (("valuePropName".equals(attr.getLocalName()))
      || ("displayPropName".equals(attr.getLocalName()))
    ){
      return;
    }
    super.generateSetAttributeByExpression(attr);
  }
  
  protected void generateTargetObservaleVaue(Attr attr){
    if ("selectedValue".equals(attr.getName())){
      out.println("new ListBoxObservableValue(" + varName + ")");
    }else if ("selectedIndex".equals(attr.getName())){
      out.println("new ListBoxIndexObservableValue(" + varName + ")");
    }else{
      super.generateTargetObservaleVaue(attr);
    }
  }

  protected void generateTargetObservaleList(Attr attr) throws NotFoundException {
    if ("values".equals(attr.getName())){
      String valuePropName = this.getAttribute("valuePropName");
      String displayPropName = this.getAttribute("displayPropName");
      if (displayPropName == null){
        displayPropName = valuePropName;
      }
      
      Node elNode = ELParser.parse(attr.getValue());
      JClassType returnType = elNode.getReturnType(elContext);
      JType elementType = null;
      if (returnType.isArray() != null){
        elementType = returnType.isArray().getComponentType();
      }else if (returnType instanceof  JParameterizedType){
        JParameterizedType parameterizedType = (JParameterizedType)returnType;
        if (TYPE_IObservableList.isAssignableFrom(parameterizedType.getRawType())){
          elementType = parameterizedType.getTypeArgs()[0];
        }
      }else if (returnType.getSuperclass() instanceof JParameterizedType){
        JParameterizedType parameterizedType = (JParameterizedType)returnType.getSuperclass();
        if (TYPE_IObservableList.isAssignableFrom(parameterizedType.getRawType())){
          elementType = parameterizedType.getTypeArgs()[0];
        }
      }
      if (elementType == null){
        throw new RuntimeException("ListBox supports array and list only.");
      }
      
      out.println("new ListBoxObservableList(" + varName + ", \"" + valuePropName + "\", \"" + displayPropName + "\"){");
      out.indent();
      out.println("protected void setValue(int index, Object obj){");
      out.indent();
      if (valuePropName == null){
        out.println("listBox.addItem(\"\" + obj, \"\" + index);");
      }else{
        out.println(elementType.getQualifiedSourceName() + " bean = (" + elementType.getQualifiedSourceName() + ")obj;");
        out.println("listBox.addItem(\"\" + bean." + elContext.getGetMethodName(displayPropName) + "(), \"\" + bean." + elContext.getGetMethodName(valuePropName) + "());");
      }
      out.outdent();
      out.println("}");
      out.outdent();
      out.println("}");
    }else{
      super.generateTargetObservaleList(attr);
    }
  }
}
